#include "Request.h"
#include "HsCallback.h"

const string OpStation = "PC;IIP=192.168.6.25;IPORT=45573;LIP=127.0.0.4;MAC=EMPTY;HD=756B3D61-56A8-4B39-AA11;PCN=NA;CPU=F2\\nBFEBFBFF000306F2;PI=YPFQ^SSS^;VOL=DPANXTJBH@HDQ;6.3.70.0";

string branch_no;
string client_id;
string fund_account;
string password = "111111";
string asset_prop;

string GetValue(const string &name)
{
	do
	{
		auto it = AllRecords.find(name);
		if (it == AllRecords.end())
		{
			this_thread::sleep_for(5ms);
			continue;
		}

		return it->second;
	} while (true);

	return {};
}

void DoGetSession(Connection *pConn)
{
	Request request(pConn);
	request.Prepare(331480);

	request.SyncSend();
	// request.SendMsg();
}

string SetSession(const char *pSession)
{
	char AuthCode[1024]{};
	strcpy(AuthCode, "hdldjfgldjgoier");

	char enSession[1024]{};
	int enLen = sizeof(enSession);
	hundsun_encrypt((char *)pSession, strlen(pSession), enSession, &enLen, AuthCode);
	return enSession;
}

void DoCheckSession(Connection *pConn)
{
	string session_id = GetValue("session_id");
	string enSession = SetSession(session_id.c_str());

	Request request(pConn);
	request.Prepare(331481);

	request.AddParam("app_id", "POBO_HD.HS_6.0.0");
	request.AddParam("session_id", session_id);
	request.AddParam("encrypted_session_id", enSession);

	request.SyncSend();
	// request.SendMsg();
}

void DoReportSystemInfo(Connection *pConn)
{
	Request request(pConn);

	request.Prepare(331482);

	request.AddParam("op_station", OpStation);

	request.AddParam("fund_account", "101302822");
	request.AddParam("session_id", GetValue("session_id"));
	request.AddParam("app_id", "POBO_HD.HS_6.0.0");

	request.AddParam("app_login_time", "2021-12-09 14:30:43");
	request.AddParam("app_public_addr", "192.168.6.25:123456");

	request.SyncSend();
	// request.SendMsg();
}

void AddCommonParam(Request &request)
{
	request.AddParam("op_entrust_way", "7");
	request.AddParam("op_station", OpStation);
	request.AddParam("password", password);
	request.AddParam("password_type", "2");
	request.AddParam("op_branch_no", branch_no);
	request.AddParam("branch_no", branch_no);
	request.AddParam("client_id", client_id);
	request.AddParam("fund_account", fund_account);
	request.AddParam("asset_prop", asset_prop);
}

void DoLogin(Connection *pConn)
{
	fmt::print("Begin DoLogin\n");
	Request request(pConn);
	request.Prepare(331100);

	request.AddParam("op_entrust_way", "7");
	request.AddParam("op_station", OpStation);
	request.AddParam("password", password);
	request.AddParam("password_type", "2");
	request.AddParam("input_content", "1");
	request.AddParam("account_content", "101302822");
	request.AddParam("content_type", "0");
	request.AddParam("ip_address", "127.0.0.1");
	request.AddParam("mac_address", "EMPTY");

	// request.SendMsg();
	request.SyncSend();

	branch_no = GetValue("branch_no");
	asset_prop = GetValue("asset_prop");
	client_id = GetValue("client_id");
	fund_account = GetValue("fund_account");
}

void TestLogin(Connection *conn)
{
	DoGetSession(conn);
	DoCheckSession(conn);
	DoReportSystemInfo(conn);
	DoLogin(conn);
	// AllRecords.clear();
}

void InsertOrder(Connection *conn)
{
	fmt::print("Begin InsertOrder\n");
	AllRecords.clear();

	Request request(conn);
	request.Prepare(338011);

	AddCommonParam(request);

	request.AddParam("exchange_type", "1");
	request.AddParam("option_code", "10005329");
	request.AddParam("option_account", "A105770220888");
	request.AddParam("entrust_amount", 1);
	request.AddParam("opt_entrust_price", 0.001);
	request.AddParam("entrust_prop", 0);
	request.AddParam("entrust_bs", 1);
	request.AddParam("entrust_oc", "O");
	request.AddParam("registe_sure_flag", 1);

	// request.SendMsg();
	request.SyncSend();
}

void Query_338067(Connection *conn)
{
	fmt::print("Begin Query_338067\n");
	AllRecords.clear();

	Request request(conn);
	request.Prepare(338067);

	AddCommonParam(request);
	request.AddParam("option_code", "");
	request.AddParam("exchange_type", "2"); // 1-上海，2-深圳
	request.AddParam("entrust_bs", "1");	// 买
	request.AddParam("entrust_oc", "O");	// 开仓
	request.AddParam("stock_type", "T");	// ETF基金

	// 发起请求
	request.SyncSend();

	fmt::print("End Query_338067\n");
}

// 订阅推送，按用户过滤
/*基本测试结果为：
 * 1. CSubscribeInterface 对象不能释放，否则使用该对象订阅的信息会无效
 * 2. 订阅时的过滤器SetFilter可以多次设置，不会覆盖原过滤信息
 * 3. 回调会通过subscribeIndex来区分，只会给对应的信息（所以，回调函数里的lpFilterData打印只会有当前推送数据的账号信息）
 */
void DoPushSubsFiterAcc(Connection *conn, std::string accountId, int type)
{
	static CSubscribeInterface *subscriber = nullptr;
	if (subscriber == nullptr)
	{
		subscriber = conn->T2Connection()->NewSubscriber(&g_SubCb, "GHD101", 5000); //
		subscriber->AddRef();
	}

	CSubscribeParamInterface *subsParam = NewSubscribeParam();
	subsParam->AddRef();
	// to do
	subsParam->SetFromNow(true);  // 是否补缺
	subsParam->SetReplace(false); // 不能覆盖
	char *lpApp = "HDTest_1";
	subsParam->SetAppData(lpApp, strlen(lpApp)); // 添加附加数据
	subsParam->SetSendInterval(0);

	if (type == 1) // 委托
	{
		subsParam->SetTopicName("secu.opt.entrust_update_notice");
	}
	else if (type == 2) // 成交
	{
		subsParam->SetTopicName("secu.opt.busin_push");
	}

	subsParam->SetFilter((char *)"fund_account", accountId.data());

	char errmsg[256]{};
	IF2UnPacker *errorPacker = NULL;
	int ret = subscriber->SubscribeTopic(subsParam, 5000, &errorPacker);

	if (errorPacker != NULL)
	{
		fmt::print("SubscribeTopic failed [{}]\n", errorPacker->GetStr("error_info"));
		errorPacker->Release();
	}

	if (ret > 0)
	{
		fmt::print("SubscribeTopic success[{}]..\n", ret);
	}

	subsParam->Release();
	// subscriber->Release(); //subscriber不能释放，否则无法收到回调方法
}

int main()
{
	Connection *conn = new Connection;
	try
	{
		TestLogin(conn);
		DoPushSubsFiterAcc(conn, "101302697", 1);
		DoPushSubsFiterAcc(conn, "101302822", 1);
		DoPushSubsFiterAcc(conn, "101302696", 1);

		// DoPushSubsFiterAcc(conn, "101302822", 2);

		this_thread::sleep_for(50ms);
		InsertOrder(conn);

		// Query_338067(conn);

		getchar();
	}
	catch (std::runtime_error &err)
	{
		printf("[happen except]: %s", err.what());
	}
}